package com.heima.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.service.AdChannelService;
import com.heima.apis.article.IArticleClient;
import com.heima.common.constants.AdChannelConstants;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.admin.dtos.AdChannelDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.common.protocol.types.Field;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Transactional
@Service
public class AdChannelServiceImpl extends ServiceImpl<AdChannelMapper, AdChannel> implements AdChannelService {
    @Override
    public ResponseResult saveChannel(AdChannelDto dto) {
        //0.条件判断
        if (dto == null || dto.getName() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "参数无效");
        }
        //0.1准备将数据更新到数据库
        AdChannel newChannel = new AdChannel();
        //1.查询数据库中所有频道，判断是否重名
        List<AdChannel> adChannels = list();
        for (AdChannel adChannel : adChannels) {
            if (adChannel.getName().equals(dto.getName())) {
                //1.1频道重名，则返回已存在
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "频道名称已存在");
            }
        }
        //1.2频道不重名，则更新属性
        newChannel.setName(dto.getName());
        //2.判断顺序号是否存在
        Integer maxOrd = 0;
        AdChannel maxOrdChannel = null;
        if (dto.getOrd() != null) {
            //2.1顺序号存在，则判断是否重复
            for (AdChannel adChannel : adChannels) {
                if (adChannel.getOrd().equals(dto.getOrd())) {
                    //2.1.1顺序号重复，则返回已存在
                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "顺序号已存在");
                }
                //2.1.1.1获取数据库中最大的顺序号--主要是想将其它这个频道设置为最大的顺序号
                maxOrd = Math.max(maxOrd, adChannel.getOrd());
            }
            /*//两种方式等效
            LambdaQueryWrapper<AdChannel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(AdChannel::getOrd, maxOrd);
            maxOrdChannel = getOne(lambdaQueryWrapper);*/
            maxOrdChannel = getOne(Wrappers.<AdChannel>lambdaQuery().eq(AdChannel::getOrd, maxOrd));
            //2.1.2顺序号不重复,判断是否大于最大的顺序号，
            //2.1.2.1大于数据库中的顺序号,更新数据库中的最大顺序号仍为最大顺序号（+1）
            if (maxOrd < dto.getOrd()) {
                maxOrdChannel.setOrd(dto.getOrd() + AdChannelConstants.AD_CHANNEL_MAXORD_ADD);
                updateById(maxOrdChannel);
            }
            //2.1.2.2小于数据库最大顺序号，更新属性
            newChannel.setOrd(dto.getOrd());
        } else {
            //2.2顺序号不存在，从数据库中选取最大的顺序号，将其值赋值到这个频道，然后更新之前最大`的顺序号（+1）
            newChannel.setOrd(maxOrd);
            maxOrdChannel.setOrd(maxOrd + AdChannelConstants.AD_CHANNEL_MAXORD_ADD);
            updateById(maxOrdChannel);
        }
        //2.3补全属性
        newChannel.setDescription(dto.getDescription());
        newChannel.setCreatedTime(new Date());
        newChannel.setIsDefault(AdChannelConstants.AD_CHANNEL_DEFAULT);  //默认为默认频道
        if (dto.getStatus()) {
            newChannel.setStatus(AdChannelConstants.AD_CHANNEL_ENABLE);
        } else {
            newChannel.setStatus(AdChannelConstants.AD_CHANNEL_DISABLE);

        }
        //2.4保存到数据库中
        save(newChannel);
        return ResponseResult.okResult(newChannel);
    }

    @Override
    public ResponseResult deleteChannel(Integer id) {
        //0.条件判断
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "参数无效");
        }
        //1.判断前端传入的id是否对应数据库中的id
        AdChannel equalAdChannel = getById(id);
        if(equalAdChannel.getName() != null && equalAdChannel.getName().equals("其他")){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "其他频道不能被删除");
        }
        if (equalAdChannel == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "数据不存在");
        }
        //1.1id在数据库中有对应频道，判断是否是禁用
        if (equalAdChannel.getStatus() != AdChannelConstants.AD_CHANNEL_DISABLE) {
            //2.1频道不是禁用状态，返回提示信息
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "频道仍被使用");
        }
        //2.2频道是禁用状态，删除数据库中对应的频道
        removeById(equalAdChannel.getId());
        return ResponseResult.okResult(equalAdChannel);
    }

    @Autowired
    private IArticleClient iArticleClient;

    @Override
    public ResponseResult updateChannel(AdChannelDto dto) {
        //0.条件判断
        if (dto == null || dto.getName() ==null ) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "参数无效");
        }
        if(dto.getName().equals("其他")){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "其他频道不能被更改");
        }
        //1.更新条件
        LambdaQueryWrapper<AdChannel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //2.根据频道名称判断是否在数据库中存储
        lambdaQueryWrapper.eq(AdChannel::getName, dto.getName());
        //2.1从数据库中拿取频道
        AdChannel adChannel = getOne(lambdaQueryWrapper);
        //2.1.1没有对应的频道，就返回提示信息
        if (adChannel == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "参数无效");
        }
        //2.1.2拿到了频道，就更新其他属性
        //2.1.2.1更新名称
        if (dto.getName() != null) {
            adChannel.setName(dto.getName());
        }
        //2.1.2.2更新描述信息
        if (dto.getDescription() != null) {
            adChannel.setDescription(dto.getDescription());
        }
        //2.1.2.3更新状态，判断频道是否被使用
        //2.1.2.3.1频道被文章使用，则不可以被禁用

        Map<String, String> map = new HashMap<>();
        map.put("channelName", dto.getName());
        List<ApArticle> apArticles = iArticleClient.articleList(map);
        boolean flag = false;
        if (apArticles.size() != 0) {
            flag = true;
        }
        if (!dto.getStatus() && flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "频道被文章引用，不能禁用");
        }
        //2.1.2.3.2频道没有被文章使用，可以被禁用
        if (!dto.getStatus()) {
            adChannel.setStatus(AdChannelConstants.AD_CHANNEL_DISABLE);
        } else {
            adChannel.setStatus(AdChannelConstants.AD_CHANNEL_ENABLE);
        }
        if (dto.getOrd()!=null) {
            //2.1.2.4更新顺序号
            //2.1.3判断顺序号是否重复
            List<AdChannel> adChannels = list();
            List<Integer> ords = new ArrayList<>();
            //2.1.4保持频道其他为最大顺序号
            Integer maxOrd = 0;
            AdChannel maxOrdChannel;
            for (AdChannel channel : adChannels) {
                ords.add(channel.getOrd());
                maxOrd = Math.max(maxOrd, channel.getOrd());
            }
            //2.2.1顺序号重复
            for (Integer ord : ords) {
                if (ord.equals(dto.getOrd()) && !adChannels.get(ords.indexOf(ord)).getId().equals(dto.getId())) {

                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "顺序号已存在");
                }
            }
            //2.2.1顺序号不重复,判断顺序号是否为最大顺序号
            LambdaQueryWrapper<AdChannel> maxLambdaQueryWrapper = new LambdaQueryWrapper<>();
            maxLambdaQueryWrapper.eq(AdChannel::getOrd, maxOrd);
            maxOrdChannel = getOne(maxLambdaQueryWrapper);
            //2.3.1顺序号不是最大顺序号
            if (dto.getOrd() != null) {
                adChannel.setOrd(dto.getOrd());
            }
            //2.3.2顺序号是最大顺序号,则保持频道其他为最大顺序号
            if (maxOrd < dto.getOrd()) {
                maxOrdChannel.setOrd(dto.getOrd() + AdChannelConstants.AD_CHANNEL_MAXORD_ADD);
                maxLambdaQueryWrapper.clear();
                maxLambdaQueryWrapper.eq(AdChannel::getId, maxOrdChannel.getId());
                update(maxOrdChannel, maxLambdaQueryWrapper);
            }
        }
        update(adChannel, lambdaQueryWrapper);
        return ResponseResult.okResult(adChannel);
    }

    @Override
    public ResponseResult channelList(AdChannelDto dto) {
        //0.条件判断
        if (dto == null || dto.getPage() == null || dto.getSize() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "参数无效");
        }
        Integer pageNum = dto.getPage();
        Integer pageSize = dto.getSize();
        IPage page = new Page(pageNum, pageSize);

        //1.查询需要按照创建时间倒序查询
        LambdaQueryWrapper<AdChannel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(AdChannel::getCreatedTime);
        //2.按照频道名称模糊查询
        if (dto.getName() != null) {
            lambdaQueryWrapper.like(AdChannel::getName, dto.getName());
        }
        //3.可以按照状态进行精确查找（1：启用--true; 0：禁用--false）
        if (dto.getStatus() != null) {
            lambdaQueryWrapper.eq(AdChannel::getStatus, dto.getStatus());
        }
        //4.分页查询
        page(page, lambdaQueryWrapper);
        List records = page.getRecords();
        return ResponseResult.okResult(records);
    }
}
